﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using StockFinder.Model;
using StockFinder.StockLists;

namespace StockFinder.TradingSystems
{
    internal abstract class BaseTradingSystem : ITradingSystem
    {
        #region ITradingSystem Members

        public TradingSystemResult Run(TradingSystemParameters parameters, IStockList stockList)
        {
            var result = new TradingSystemResult();
            return result;
        }

        public TradingSystemResult Run(TradingSystemParameters parameters, Symbol symbol)
        {
            var result = new TradingSystemResult();                        
            var openNewPosition = false;
            var adjustTrailingStopLoss = false;
            var stopWatch = new Stopwatch();
            stopWatch.Start();
            var priceCount = symbol.Prices.Count;
            var pricesArray = symbol.Prices.OrderBy(p => p.PriceDate).ToArray();

            //loop prices
            for (var i = 0; i < priceCount; i++)
            {
                #region Daily variables                           
                TodayPrice = pricesArray[i];
                YesterdayPrice = pricesArray[i - 1];
                #endregion

                //do we need to close open position?
                if (Trade != null)
                {
                    //use greater of trailing and hard
                    var stopLossToCheck = (Trade.HardStopLoss > Trade.TrailingStopLoss)
                                              ? Trade.HardStopLoss
                                              : Trade.TrailingStopLoss;

                    //did we break the stop loss?                    
                    if (YesterdayPrice.AdjustedClose < stopLossToCheck)
                    {
                        Trade.ExitDate = TodayPrice.PriceDate;
                        Trade.ExitPrice = TodayPrice.AdjustedOpen;
                        Trade.IsOpen = false;
                        Trade = null; //reset position                       
                    }
                }


                if (PassesAfterMarketChecks())
                {
                    if (Trade != null)
                    {
                        openNewPosition = true;
                    }
                    else
                    {
                        adjustTrailingStopLoss = true;
                    }
                }                
            }            

            return result;
        }

        #endregion

        protected abstract void ApplyTechnicalIndicators();

        protected abstract bool PassesAfterMarketChecks();

        protected abstract decimal GetStopLoss();

        protected Trade Trade { get; private set; }
        protected DailyPrice TodayPrice { get; private set; }
        protected DailyPrice YesterdayPrice { get; private set; }
    }
}
